
using System;
using System.Text;
using GeoFramework;

namespace GeoFramework.Gps.Nmea
{
	/// <summary>Represents a $GPVTG sentence describing bearing and speed.</summary>
	public sealed class GpvtgSentence : NmeaSentence
	{
		private Azimuth pTrueBearing;
		private Azimuth pMagneticBearing;
		private Speed pSpeed;

		#region Constructors 

		public GpvtgSentence(string sentence) : base(sentence)
		{
			// Is the checksum valid?
			if (!IsValid && !IsPartialSentenceParsingAllowed)
			{
				pTrueBearing = Azimuth.Empty;
				pMagneticBearing = Azimuth.Empty;
				pSpeed = Speed.Empty;
				// No.  Do no parsing
				return;
			}

			//		VTG - Track Made Good and Ground Speed 
			//		The actual track made good and speed relative to the ground. 
			//		$--VTG,x.x,T,x.x,M,x.x,N,x.x,K 
			//	  0	1  2  3  4  5  6  7  8   Words()
			//	  1	2  3  4  5  6  7  8  9   WordLength
			//		x.x,T = Track, degrees True 
			//		x.x,M = Track, degrees Magnetic 
			//		x.x(, N = Speed, knots)
			//		x.x(, K = Speed, Km / hr)
			//Try
			try
			{
				if(WordCount > 1 && Words[1].Length != 0)
						pTrueBearing = Azimuth.Parse(Words[1], NmeaCultureInfo);
				else
					pTrueBearing = Azimuth.Empty;

				if(WordCount > 3 && Words[3].Length != 0)
						pMagneticBearing = Azimuth.Parse(Words[3], NmeaCultureInfo);
				else
					pMagneticBearing = Azimuth.Empty;
						
				if(WordCount > 6 && Words[5].Length != 0 && Words[6].Length != 0)
				{
					pSpeed = new Speed(
						double.Parse(Words[5], NmeaCultureInfo),
						Words[6] == "N" ? SpeedUnit.Knots : SpeedUnit.KilometersPerHour).ToLocalUnitType();

					//						switch (Words[6].ToUpper(NmeaCultureInfo))
					//						{
					//							case "N":
					//								pSpeed = new Speed(double.Parse(Words[5], NmeaCultureInfo), SpeedUnit.Knots).ToLocalUnitType();
					//								break;
					//							case "K":
					//								pSpeed = new Speed(double.Parse(Words[5], NmeaCultureInfo), SpeedUnit.KilometersPerHour).ToLocalUnitType();
					//								break;
					//						}					
				}
				else
					pSpeed = Speed.Empty;
			}
			catch(Exception ex)
			{
				throw new NmeaSentenceException(this, "A $GPVTG sentence contained unrecognizable data.", ex);
			}			
		}

		public GpvtgSentence(byte[] bytes) 
            : this(ASCIIEncoding.ASCII.GetString(bytes, 0, bytes.Length))
		{
		}

		//[CLSCompliant(false)]
		public GpvtgSentence(Azimuth trueBearing, Azimuth magneticBearing, Speed speed)
		{
			pTrueBearing = trueBearing;
			pMagneticBearing = magneticBearing;
			pSpeed = speed;
			// Output the information as a GPGGA sentence (!!)
			StringBuilder Sentence = new StringBuilder();
			Sentence.Append("$GPVTG,")
				// Output track, degrees true
				.Append(TrueBearing.ToString("d.d"))
				.Append(",T,")
				// Output track, degrees true
				.Append(MagneticBearing.ToString("d.d"))
				.Append(",M,")
				// Output speed in knots
				.Append(Speed.ToKnots().ToString("v.v"))
				.Append(",N,")
				// Output speed in KM/H
				.Append(Speed.ToKilometersPerHour().ToString("v.v"))
				.Append(",K");
			// Set the sentence
			SetSentence(Sentence.ToString());
			SetChecksum();
		}

		#endregion

		#region Public Members

		/// <summary>Returns the current direction of travel in relation to True North.</summary>
		public Azimuth TrueBearing 
		{
			get
			{
				return pTrueBearing;
			}
		}

		/// <summary>Returns the current direction of travel in relation to Magnetic North.</summary>
		public Azimuth MagneticBearing 
		{
			get
			{
				return pMagneticBearing;
			}
		}

		/// <summary>Returns the current rate of travel.</summary>
		public Speed Speed 
		{
			get
			{
				return pSpeed;
			}
		}

		#endregion

		#region Static Members

		/// <summary>Represents a $GPVTG sentence with empty values.</summary>
		public static readonly GpvtgSentence Empty = new GpvtgSentence(Azimuth.Empty, Azimuth.Empty, 
			Speed.Empty);

		/// <summary>Returns a new instance by interpreting the specified string.</summary>
		public static GpvtgSentence Parse(string sentence)
		{
			return new GpvtgSentence(sentence);
		}

		/// <summary>
		/// Indicates that this sentence is supported by GPS.NET.
		/// </summary>
		public override bool IsSupported
		{
			get
			{
				return true;
			}
		}

		#endregion
	}
}
